/**
 * 
 */
package com.net.server.netty;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;


/**
 * Netty 支持的 io接口防火墙 , 过滤一些IP
 */
public class FirewallFilter extends SimpleChannelHandler {

	/**
	 * 阻止的IP地址
	 */
	private final List<InetAddress> prohibitlList = new CopyOnWriteArrayList<InetAddress>();

//	private static Logger logger = Logger.getLogger(FirewallFilter.class);

	@Override
	public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {

		if (e instanceof ChannelStateEvent) {
		//	LoggerManager.Netty.debug("FirewallFilter Channel state changed: " + e);
			ChannelStateEvent evt = (ChannelStateEvent) e;
			switch (evt.getState()) {
			case OPEN:
				if (Boolean.TRUE.equals(evt.getValue())) {
					if (this.isLegal(ctx)) {
						channelOpen(ctx, evt);
						ctx.getChannel();
					}
				} else {
					channelClosed(ctx, evt);
				}
				break;
			case BOUND:
				if (evt.getValue() != null) {
					channelBound(ctx, evt);
				} else {
					channelUnbound(ctx, evt);
				}
				break;
			case CONNECTED:
				if (evt.getValue() != null) {
					channelConnected(ctx, evt);
				} else {
					channelDisconnected(ctx, evt);
				}
				break;
			case INTEREST_OPS://改变通道的interestOps.
				channelInterestChanged(ctx, evt);
				break;
			default:
				ctx.sendUpstream(e);
			}
		} else {
			super.handleUpstream(ctx, e);
		}
	}

	@Override
	public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
		// Log all channel state changes.
		if (e instanceof MessageEvent) {
			// logger.info("Writing:: " + e);
		}
		
		super.handleDownstream(ctx, e);
	}

	/**
	 * Invoked when a message object (e.g: {@link ChannelBuffer}) was received
	 * from a remote peer.
	 */
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
		ctx.sendUpstream(e);
	}
	
	/**
	 * 验证会话是否合法
	 * 
	 * @param session
	 * @return
	 */
	private boolean isLegal(ChannelHandlerContext ctx) {
		if (prohibitlList.isEmpty()) {
			return true;
		}
		SocketAddress remoteAddress = ctx.getChannel().getRemoteAddress();
		if (remoteAddress instanceof InetSocketAddress) {
			if (prohibitlList.contains(((InetSocketAddress) remoteAddress).getAddress())) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 设置设置阻止列表
	 * 
	 * @param addresses
	 */
	public void setLegallist(InetAddress[] addresses) {
		if (addresses == null) {
			return;
		}
		prohibitlList.clear();
		for (int i = 0; i < addresses.length; i++) {
			InetAddress addr = addresses[i];
			prohibit(addr);
		}
	}

	/**
	 * 设置设置阻止列表
	 * 
	 * @param addresses
	 */
	public void setLegallist(InetAddress addresses) {
		if (addresses == null) {
			return;
		}
		prohibitlList.clear();
		prohibit(addresses);
	}

	public void prohibit(InetAddress address) {
		if (address == null) {
			return;
		}
		prohibitlList.add(address);
	}
}
